package cn.david.user.service.impl;


import cn.david.basic.constant.UserConstants;
import cn.david.basic.constant.WxConstants;
import cn.david.basic.exception.BusinessExcepiton;
import cn.david.basic.util.AjaxResult;
import cn.david.basic.util.HttpClientUtils;
import cn.david.basic.util.MD5Utils;
import cn.david.basic.util.StrUtils;
import cn.david.user.domian.Logininfo;
import cn.david.user.domian.User;
import cn.david.user.domian.WxUser;
import cn.david.user.dto.LoginDto;
import cn.david.user.mapper.LogininfoMapper;
import cn.david.user.mapper.UserMapper;
import cn.david.user.mapper.WxUserMapper;
import cn.david.user.service.ILoginService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements ILoginService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private WxUserMapper wxUserMapper;
    @Autowired
    private UserMapper userMapper;
    @Override
    public Map<String, Object> loginAccount(LoginDto loginDto) {
        if (StringUtils.isEmpty(loginDto.getUsername())
                ||StringUtils.isEmpty(loginDto.getPassword())
                ||StringUtils.isEmpty(loginDto.getType())){
            throw new BusinessExcepiton("请输入完整信息");
        }
        Logininfo info = logininfoMapper.loadByUser(loginDto);
        if (info==null){
            throw new BusinessExcepiton("用户不存在");
        }
        String salt = info.getSalt();
        String md5 = MD5Utils.encrypByMd5(loginDto.getPassword() + salt);
        if (!md5.equals(info.getPassword())){
            throw new BusinessExcepiton("账号或者密码输入错误");
        }
        if (info.getDisable()!=1){
            throw new BusinessExcepiton("账号被冻结，请联系客服");
        }
        //默认uuid是32位
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, info, 30, TimeUnit.MINUTES);
        Map <String,Object> map = new HashMap<>();
        map.put("token",token );
        info.setSalt(null);
        info.setPassword(null);
        map.put("logininfo",info);
        return map;
    }

    @Override
    public AjaxResult wecohatLogin(String code) {
        String getTokenUrl = WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);
        String tokenStr = HttpClientUtils.httpGet(getTokenUrl);
        if (StringUtils.isEmpty(tokenStr)){
            throw new BusinessExcepiton("获取CODE失败");
        }
        JSONObject tokenObj = JSONObject.parseObject(tokenStr);
        String accessToken = tokenObj.getString("access_token");
        String openId = tokenObj.getString("openid");
        WxUser wxUser = wxUserMapper.loadByOpenId(openId);
        System.out.println(wxUser+"=========================");
        if (wxUser!=null && wxUser.getUser_id()!=null){
            Logininfo info = logininfoMapper.loadByUserId(wxUser.getUser_id());
            String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(token, info, 30,TimeUnit.MINUTES);
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            info.setPassword(null);
            info.setSalt(null);
            map.put("logininfo", info);
            return AjaxResult.me().setResultObj(map);
        }else {
            String resultUrlParam ="accessToken="+accessToken+"&openId="+openId;
            return AjaxResult.me().setSuccess(false).setResultObj(resultUrlParam);
        }

    }

    @Override
    public Map<String, Object> wecohatbinder(Map<String, String> param) {
        String phone = param.get("phone");
        String verifyCode = param.get("verifyCode");
        String accessToken = param.get("accessToken");
        String openId = param.get("openId");
        if (StringUtils.isEmpty(phone)||StringUtils.isEmpty(verifyCode)||
                StringUtils.isEmpty(accessToken)||StringUtils.isEmpty(openId)) {
            throw new BusinessExcepiton("请输入完整信息");
        }
        //2 验证码校验  不要区分大小写
        Object o = redisTemplate.opsForValue().get(UserConstants.BINDER_CODE_PREFIX + phone);
        if (o==null){
            throw new BusinessExcepiton("验证码已失效");
        }
        String code =((String)o).split(":")[0];
        if (!code.equalsIgnoreCase(verifyCode)){
            throw new BusinessExcepiton("验证码错误");
        }
        User user = userMapper.loadByphone(phone);
        Logininfo info=null;
        if (user==null){
            user = initUserByPhone(phone);
            info = user2LoginInfo(user);
            logininfoMapper.save(info);
            user.setLogininfo_id(info.getId() );
            userMapper.save(user);
        }else {
            info =logininfoMapper.loadById(user.getLogininfo_id());
        }
        String getUserUrl = WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openId);

        String wxUserStr = HttpClientUtils.httpGet(getUserUrl);
        if (StringUtils.isEmpty(wxUserStr)){
            throw new BusinessExcepiton("获取CODE失败");
        }
        WxUser wxUser = user2WxUser(wxUserStr, user);
        wxUserMapper.save(wxUser);
        //免密登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, info, 30,TimeUnit.MINUTES);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        info.setPassword(null);
        info.setSalt(null);
        map.put("logininfo", info);
        return map;
    }

    private Logininfo user2LoginInfo(User user) {
        Logininfo info = new Logininfo();
        BeanUtils.copyProperties(user, info);
        info.setType(1);
        return info;

    }

    private User initUserByPhone(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        //生成随机32位的salt
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = MD5Utils.encrypByMd5(StrUtils.getComplexRandomString(6)+ salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        return user;
    }

    private WxUser user2WxUser(String wxUserStr, User user) {
        //装换微信用户信息
        JSONObject jsonObject = JSONObject.parseObject(wxUserStr);
        WxUser wxUser =  new WxUser();
        wxUser.setUser_id(user.getId());
        wxUser.setOpenid(jsonObject.getString("openid"));
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setAddress(null);
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        return wxUser;
    }
}
